home *** CD-ROM | disk | FTP | other *** search
- Subject: v18i028: Mail user's shell version 6.4, Part06/19
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: Dan Heller <island!argv@sun.com>
- Posting-number: Volume 18, Issue 28
- Archive-name: mush6.4/part06
-
-
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 6 (of 19)."
- # Contents: curs_io.c pick.c select.c viewopts.c
- # Wrapped by rsalz@papaya.bbn.com on Mon Mar 13 19:25:12 1989
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'curs_io.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'curs_io.c'\"
- else
- echo shar: Extracting \"'curs_io.c'\" \(12588 characters\)
- sed "s/^X//" >'curs_io.c' <<'END_OF_FILE'
- X/* @(#)curs_io.c (c) copyright 3/18/87 (Dan Heller) */
- X
- X/* curs_io.c -- curses based I/O */
- X#include "mush.h"
- X#include "bindings.h"
- X
- Xstatic backspace();
- X
- Xchar *_unctrl[] = {
- X "^@", "^A", "^B", "^C", "^D", "^E", "^F", "^G", "^H", "^I", "^J", "^K",
- X "^L", "^M", "^N", "^O", "^P", "^Q", "^R", "^S", "^T", "^U", "^V", "^W",
- X "^X", "^Y", "^Z", "^[", "^\\", "^]", "^~", "^_",
- X " ", "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*", "+", ",", "-",
- X ".", "/", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":", ";",
- X "<", "=", ">", "?", "@", "A", "B", "C", "D", "E", "F", "G", "H", "I",
- X "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W",
- X "X", "Y", "Z", "[", "\\", "]", "^", "_", "`", "a", "b", "c", "d", "e",
- X "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s",
- X "t", "u", "v", "w", "x", "y", "z", "{", "|", "}", "~", "^?"
- X};
- X
- Xchar del_line; /* tty delete line character */
- Xchar del_word; /* tty delete word character */
- Xchar del_char; /* backspace */
- Xchar reprint_line; /* usually ^R */
- Xchar eofc; /* usually ^D */
- Xchar lit_next; /* usually ^V */
- X
- Xtty_settings()
- X{
- X savetty();
- X
- X#ifdef SYSV
- X eofc = _tty.c_cc[VEOF];
- X#else
- X#ifdef BSD
- X if (ioctl(0, TIOCGETC, &tchars) != -1)
- X eofc = tchars.t_eofc;
- X else
- X#endif /* BSD */
- X eofc = CTRL(D);
- X#endif /* SYSV */
- X
- X if (!isatty(0)) {
- X del_line = CTRL(U);
- X del_char = CTRL(H);
- X } else {
- X del_line = _tty.sg_kill;
- X del_char = _tty.sg_erase;
- X }
- X
- X#ifdef TIOCGLTC
- X if (ioctl(0, TIOCGLTC, <chars) != -1) {
- X del_word = ltchars.t_werasc;
- X reprint_line = ltchars.t_rprntc;
- X lit_next = ltchars.t_lnextc;
- X } else
- X#endif /* TIOCGLTC */
- X {
- X del_word = CTRL(W);
- X reprint_line = CTRL(R);
- X lit_next = CTRL(V);
- X }
- X}
- X
- X#ifdef Addch
- X#undef Addch
- X#endif /* Addch */
- X
- X#ifndef CURSES
- X
- X/* Make sure all ifs have matching elses! */
- X
- X#define Addch(c) \
- X if (ison(glob_flags, ECHO_FLAG)) \
- X {;} \
- X else \
- X fputc(c, stdout), fflush(stdout)
- X
- X#else
- X
- X/* see end of Getstr */
- X#define Addch(c) \
- X if (iscurses) \
- X addch(c), refresh(); \
- X else if (ison(glob_flags, ECHO_FLAG)) \
- X {;} \
- X else \
- X fputc(c, stdout), fflush(stdout)
- X#endif /* CURSES */
- X
- X/*
- X * get a string of at most 'length' chars.
- X * allow backspace-space-backspace, kill word and kill line
- X * (options set by user in stty).
- X * length is the max length this string can get. offset is from beginning
- X * of string.
- X * input of ^D returns -1; otherwise, return the number of chars in string.
- X */
- XGetstr(String, length, offset)
- Xchar String[];
- Xregister int length;
- X{
- X register int c, literal_next = FALSE, lit_bs = FALSE;
- X struct cmd_map *curr_map;
- X int count = offset, save_wc = wrapcolumn;
- X
- X fflush(stdout); /* make sure everything is flushed before getting input */
- X
- X if (mac_hide) {
- X curr_map = NULL_MAP;
- X wrapcolumn = 0;
- X } else if (ison(glob_flags, IS_GETTING))
- X curr_map = bang_map;
- X else if (iscurses)
- X curr_map = NULL_MAP;
- X else
- X curr_map = line_map;
- X
- X while ((c = m_getchar()) != '\n' && c != '\r' && c != EOF &&
- X isoff(glob_flags, WAS_INTR)) {
- X /* echo isn't set, so whatever the character, enter it */
- X if (ison(glob_flags, QUOTE_MACRO) || ison(glob_flags, ECHO_FLAG)) {
- X if (count < length) {
- X String[count++] = c;
- X /* Note: Addch includes ECHO_FLAG test */
- X if (iscntrl(c)) {
- X Addch('^');
- X Addch(_unctrl[c][1]);
- X } else
- X Addch(c);
- X } else {
- X print("Warning: string too long. Truncated at %d chars.\n",
- X length);
- X break;
- X }
- X }
- X /* ^D as the first char on a line or two ^D's in a row is EOF */
- X else if (c == eofc && !count)
- X break;
- X else if (c == '\\' && count < length) {
- X literal_next = TRUE, lit_bs = FALSE;
- X Addch(String[count++] = '\\');
- X } else if (c == lit_next && count < length) {
- X literal_next = lit_bs = TRUE;
- X String[count++] = '\\';
- X if (!in_macro()) {
- X /* if (iscntrl(c)) */
- X Addch('^');
- X /* Addch(_unctrl[c][1]); */
- X }
- X } else if (literal_next) {
- X struct cmd_map *list;
- X
- X literal_next = FALSE;
- X if (iscntrl(c) || c == del_line || c == del_char || c == del_word
- X || c == lit_next || lit_bs)
- X if (!in_macro() || !lit_bs)
- X backspace(String, &count);
- X else
- X --count;
- X else if (in_macro() && c == MAC_LONG_CMD)
- X --count;
- X /* check to see if user is escaping a map or map! */
- X else
- X for (list = curr_map; list; list = list->m_next)
- X if (list->m_str[0] == c) {
- X if (!in_macro())
- X backspace(String, &count);
- X else
- X --count;
- X break;
- X }
- X /* A literal-next advances the macro offset */
- X String[count++] = c;
- X if (iscntrl(c) || c == del_char) {
- X if (iscntrl(c)) {
- X /*
- X * Decrement wrapcolumn because two chars added.
- X * It will be restored from save_wc before return.
- X */
- X if (wrapcolumn > 1)
- X wrapcolumn--;
- X Addch('^');
- X }
- X Addch(_unctrl[c][1]);
- X } else
- X Addch(c);
- X } else if (c == del_line) {
- X if (count) {
- X do
- X backspace(String, &count);
- X while (count);
- X }
- X } else
- X if (c == reprint_line)
- X String[count] = 0, wprint("\n%s", String);
- X else
- X if (c == del_word) /* word erase */
- X while (count) {
- X backspace(String, &count);
- X if (!count ||
- X isspace(String[count-1]) && !isspace(String[count]) ||
- X !isalnum(String[count-1]) && isalnum(String[count]))
- X break;
- X }
- X else if (c == del_char || c == CTRL(H) || c == 127 /* CTRL(?) */) {
- X if (count)
- X backspace(String, &count);
- X /* if iscurses, then backspacing too far cancels a function */
- X else if (!count && iscurses && isoff(glob_flags, LINE_MACRO)) {
- X mac_flush();
- X String[0] = '\0';
- X wrapcolumn = save_wc;
- X return -1;
- X }
- X } else if (count == length)
- X bell();
- X else if (c == '\t')
- X do {
- X /* Yuck -- tabs break map! */
- X Addch(' ');
- X String[count] = ' ';
- X } while (++count % 8 && count < length);
- X else if (in_macro() && c == MAC_LONG_CMD) {
- X char cbuf[MAX_LONG_CMD + 1];
- X
- X if ((c = read_long_cmd(cbuf)) == 0) {
- X c = MAC_LONG_CMD;
- X goto check_expand; /* How could I avoid this? */
- X } else if (c > 0) {
- X int ok;
- X
- X String[count] = '\0';
- X if ((ok = reserved_cmd(cbuf, TRUE)) > 0) {
- X /* Reprint the line */
- X if (iscurses)
- X print(":%s", String);
- X else
- X wprint("\r%s", String);
- X continue; /* Get next char without changing count */
- X } else if (ok < 0) {
- X String[offset] = '\0';
- X wrapcolumn = save_wc;
- X return ok;
- X } else
- X goto push_back;
- X } else {
- X /*
- X * Ooops. We read a bunch of stuff we should not
- X * have read, because this isn't really a long command.
- X * Use a trick to push the whole thing back, ala ungetc.
- X * Wouldn't it be nifty if stdio worked this way? :-)
- X */
- Xpush_back:
- X if (c > 0) {
- X cbuf[c++] = MAC_LONG_END;
- X cbuf[c] = '\0';
- X }
- X c = MAC_LONG_CMD;
- X Ungetstr(cbuf);
- X goto check_expand; /* How could I avoid this goto? */
- X }
- X } else {
- Xcheck_expand:
- X if (!curr_map || !check_map(c, curr_map)) {
- X /* else if (match != MATCH) */
- X if (c != '\t' && iscntrl(c)) {
- X Addch('^');
- X Addch(_unctrl[c][1]);
- X /* Decrement wrapcolumn as above */
- X if (wrapcolumn > 1)
- X wrapcolumn--;
- X } else
- X Addch(c);
- X String[count++] = c;
- X }
- X }
- X /* Null-terminate for macro lookup purposes.
- X * This will be overwritten by the next character.
- X */
- X String[count] = '\0';
- X if (line_wrap(String, &count))
- X break;
- X }
- X fflush(stdout); /* for sys-v folks */
- X
- X if (c == eofc || c == EOF || ison(glob_flags, WAS_INTR)) {
- X if (feof(stdin))
- X clearerr(stdin);
- X wrapcolumn = save_wc;
- X return -1;
- X }
- X if (count && String[count-1] == '\\') {
- X int count2;
- X if (isoff(glob_flags, ECHO_FLAG))
- X putchar('\n');
- X wrapcolumn = save_wc;
- X /*
- X * NOTE: If the offset passed here is ever made greater than 0,
- X * the value of wrapcolumn must again be changed/restored ...
- X */
- X if ((count2 = Getstr(&String[count-1], length - count + 1, 0)) == -1)
- X return -1;
- X return count + count2;
- X }
- X if (!iscurses && isoff(glob_flags, ECHO_FLAG))
- X putchar('\n');
- X /* Should be null-terminated already, but just in case */
- X String[count] = '\0';
- X wrapcolumn = save_wc;
- X return count;
- X}
- X
- Xstatic
- Xbackspace(str, n)
- Xregister char *str;
- Xint *n;
- X{
- X (*n)--;
- X Addch('\b'); Addch(' '); Addch('\b');
- X if (iscntrl(str[*n])) {
- X Addch('\b'); Addch(' '); Addch('\b');
- X /* Re-increment wrapcolumn -- see Getstr */
- X if (wrapcolumn)
- X wrapcolumn++;
- X }
- X}
- X
- X#undef Addch
- X
- X/*
- X * Check to see if what the user is typing is supposed to be expanded
- X * into a longer string. The first char is 'c' and the map list to use
- X * is in map_list. Continue looping (reading chars from stdin or a
- X * currently active mapping) until a match happens or we've determined
- X * that there is no match.
- X */
- Xcheck_map(c, map_list)
- Xchar c;
- Xstruct cmd_map *map_list;
- X{
- X char mbuf[MAX_MACRO_LEN], *p = mbuf;
- X struct cmd_map *list;
- X int m, n, match;
- X
- X *p++ = c;
- X
- X while (isoff(glob_flags, WAS_INTR)) {
- X m = 0;
- X *p = 0; /* make sure it's null terminated */
- X /*
- X * loop thru the list of maps and check to see if the typed
- X * char matches the mapping. If it matches completely, substitute
- X * the stuff in x_str and return. If a partial match occurs, then
- X * read the next char until a timeout or no match.
- X */
- X for (list = map_list; list; list = list->m_next) {
- X if ((match = prefix(mbuf, list->m_str)) == MATCH) {
- X /* Must turn on flags BEFORE pushing */
- X line_macro(list->x_str);
- X return 1;
- X } else if (match != NO_MATCH)
- X m++; /* something matched partially */
- X }
- X if (!m)
- X break;
- X /* see if there's anything on the queue to read... */
- X if (mac_pending()
- X#ifdef FIONREAD
- X || !ioctl(0, FIONREAD, &n) && n > 0
- X#endif /* FIONREAD */
- X )
- X *p++ = m_getchar();
- X else {
- X /* The user has typed the first part of a map or macro. Give him
- X * a chance to finish it.
- X */
- X#if defined(BSD) || defined(SELECT)
- X /* If the system has select(), use it. It's much faster and
- X * more aesthetic since there is no mandatory timeout.
- X */
- X struct timeval timer;
- X#ifdef FD_SET
- X fd_set rmask, wmask, xmask;
- X FD_SET(0, &rmask); /* Test stdin for read */
- X FD_ZERO(&wmask); /* Don't care about write */
- X FD_ZERO(&xmask); /* Don't care about exception */
- X#else
- X int rmask = 1, wmask = 0, xmask = 0;
- X#endif /* FD_SET */
- X timer.tv_sec = 1;
- X timer.tv_usec = 0;
- X n = select(1, &rmask, &wmask, &xmask, &timer);
- X#else /* !SELECT */
- X#ifdef FIONREAD
- X /* system doesn't have select(), so use FIONREAD to see if
- X * there are any chars on the queue to read.
- X */
- X (void) sleep(1);
- X (void) ioctl(0, FIONREAD, &n);
- X#else
- X /* system has neither select() nor FIONREAD, so just set n
- X * and force the user to either complete the map or fail it
- X * without a timeout. Chars won't echo till he does one or
- X * the other.
- X */
- X n = 1;
- X#endif /* FIONREAD */
- X#endif /* SELECT */
- X if (n > 0)
- X /* don't read all 'n' chars -- there may be a match early */
- X *p++ = m_getchar(); /* To flush macros and reset flags */
- X else /* still nothing to read? User doesn't want to use map */
- X break;
- X }
- X }
- X /* no match or a timeout. This isn't a map, just return. */
- X *p = 0;
- X if (mbuf[1])
- X mac_push(mbuf + 1);
- X return 0;
- X}
- X
- X/*
- X * Check for line wrap. This should happen only in composition mode and
- X * only when the variable wrapcolumn has a value greater than zero. Line
- X * wrap is implemented using Ungetstr [that is, mac_push()].
- X *
- X * Returns 1 if the line was wrapped, 0 if not.
- X */
- Xline_wrap(string, count)
- Xchar *string; /* The string to be wrapped */
- Xint *count; /* Offset of string terminator */
- X{
- X char *tail = NULL;
- X int n = *count;
- X
- X if (wrapcolumn < 1 || *count <= wrapcolumn
- X || isoff(glob_flags, IS_GETTING) /* Wrap only in msg body */
- X || ison(glob_flags, QUOTE_MACRO) /* Don't wrap quoted macros */
- X || ison(glob_flags, ECHO_FLAG)) /* Can't wrap in echo mode */
- X return 0;
- X
- X /* Back up past the wrapcolumn point */
- X for (; n > wrapcolumn; --n)
- X ;
- X /* Look for a space */
- X while (n && !isspace(string[n]))
- X --n;
- X /* If no break found, return no wrap */
- X if (!n)
- X return 0;
- X tail = &string[n+1];
- X /* Skip the break char and any whitespace */
- X while (n && isspace(string[n]))
- X --n;
- X ++n; /* move back into the whitespace */
- X /* Erase the stuff that will wrap */
- X while (*count > n)
- X backspace(string,count);
- X string[*count] = '\0';
- X /* Push the tail, if any */
- X if (*tail)
- X Ungetstr(tail);
- X return 1;
- X}
- END_OF_FILE
- if test 12588 -ne `wc -c <'curs_io.c'`; then
- echo shar: \"'curs_io.c'\" unpacked with wrong size!
- fi
- # end of 'curs_io.c'
- fi
- if test -f 'pick.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'pick.c'\"
- else
- echo shar: Extracting \"'pick.c'\" \(13226 characters\)
- sed "s/^X//" >'pick.c' <<'END_OF_FILE'
- X/* @(#)pick.c 2.4 (c) copyright 10/18/86 (Dan Heller) */
- X
- X#include "mush.h"
- X
- Xstatic int before, after, search_from, search_subj, search_to, xflg, icase;
- Xstatic mdy[3], search_hdr[64];
- Xstatic int pick();
- X
- Xdo_pick(n, argv, list)
- Xregister int n;
- Xregister char **argv, list[];
- X{
- X char ret_list[MAXMSGS_BITS];
- X
- X if (n > 1 && !strcmp(argv[1], "-?"))
- X return help(0, "pick", cmd_help);
- X
- X /* if is_pipe, then the messages to search for are already set.
- X * if not piped, then reverse the bits for all message numbers.
- X * That is, search EACH message. only those matching will be returned.
- X */
- X if (isoff(glob_flags, IS_PIPE))
- X bitput(list, list, msg_cnt, =~) /* macro, turn on all bits */
- X clear_msg_list(ret_list);
- X if (pick(n, argv, list, ret_list, isoff(glob_flags, DO_PIPE)) == -1)
- X return -1;
- X if (istool && isoff(glob_flags, DO_PIPE))
- X print("Messages: ");
- X for (n = 0; n < msg_cnt; n++)
- X if (msg_bit(ret_list, n) && !xflg ||
- X !msg_bit(ret_list, n) && xflg) {
- X if (isoff(glob_flags, DO_PIPE))
- X if (istool)
- X print_more("%d ", n+1);
- X else
- X print("%s\n", compose_hdr(n));
- X set_msg_bit(list, n);
- X } else
- X unset_msg_bit(list, n);
- X return 0;
- X}
- X
- X/*
- X * search for messages. Even if no messages match, return 0. Errors such
- X * as internal errors or syntax errors, return -1.
- X */
- Xstatic int
- Xpick(ret, argv, list, ret_list, verbose)
- Xregister int ret;
- Xregister char **argv, list[], ret_list[];
- X{
- X register char c;
- X char pattern[256];
- X int o_before = before, o_after = after, o_search_from = search_from,
- X o_search_subj = search_subj, o_search_to = search_to, o_mdy[3], n;
- X
- X for (c = 0; c < 3; c++)
- X o_mdy[c] = mdy[c];
- X
- X ret = -1;
- X if (!msg_cnt) {
- X print("No Messages.\n");
- X goto bad;
- X }
- X
- X icase = before = after = search_from = search_subj = xflg = 0;
- X mdy[0] = search_hdr[0] = 0;
- X while (*argv && *++argv && **argv == '-')
- X switch(c = argv[0][1]) {
- X /* users specifies a range */
- X case 'r': {
- X int X = 2;
- X /* if not a pipe, then clear all bits cuz we only want
- X * to search the message specified here...
- X * If it is a pipe, then add to the messages searched for.
- X */
- X if (isoff(glob_flags, IS_PIPE))
- X clear_msg_list(list);
- X /* "-r10-15"
- X * ^argv[1][2] if NULL, then
- X * list detached from "r" e.g. "-r" "5-20"
- X */
- X if (!argv[0][X])
- X argv++, X = 0;
- X (*argv) += X;
- X n = get_msg_list(argv, list);
- X (*argv) -= X;
- X if (n == -1)
- X goto bad;
- X argv += (n-1); /* we're going to increment another up top */
- X }
- X when 'a': {
- X if ((n = ago_date(++argv)) == -1)
- X goto bad;
- X argv += n;
- X }
- X when 'd':
- X if (!*++argv) {
- X print("specify a date for -%c\n", c);
- X goto bad;
- X }
- X if (!date1(*argv))
- X goto bad;
- X when 's' : case 'f': case 't': case 'h':
- X if (search_subj + search_from + search_to + *search_hdr > 1) {
- X print("specify one of `s', `f', `t' or `h' only\n");
- X goto bad;
- X }
- X if (c == 's')
- X search_subj = 1;
- X else if (c == 'f')
- X search_from = 1;
- X else if (c == 'h')
- X if (!*++argv)
- X print("Specify header to search for.\n");
- X else
- X (void) lcase_strcpy(search_hdr, *argv);
- X else
- X search_to = 1;
- X when 'x' : xflg = 1;
- X when 'i' : icase = 1;
- X otherwise:
- X print("pick: unknown flag: %c\n", argv[0][1]);
- X clear_msg_list(ret_list);
- X return -1;
- X }
- X pattern[0] = 0;
- X (void) argv_to_string(pattern, argv);
- X if (verbose) {
- X print_more("Searching for messages");
- X if (mdy[1] == 0) {
- X print(" that %scontain \"%s\"", (xflg)? "does not ": "",
- X (*pattern)? pattern: "<previous expression>");
- X if (search_subj)
- X print_more(" in subject line");
- X else if (search_from)
- X print_more(" from author names");
- X else if (search_to)
- X print_more(" from the To: field");
- X else if (search_hdr[0])
- X print_more(" from the message header: \"%s:\"", search_hdr);
- X } else {
- X extern char *month_names[]; /* from dates.c */
- X print_more(" dated ");
- X if (before || after)
- X if (xflg)
- X print_more("%s ", (!before)? "before": "after");
- X else
- X print_more("on or %s ", (before)? "before": "after");
- X print_more("%s. %d, 19%d.",
- X month_names[mdy[0]], mdy[1], mdy[2]);
- X }
- X print_more("\n");
- X }
- X if (mdy[1] > 0 && icase)
- X print("using date: -i flag ignored.\n");
- X ret = find_pattern(pattern, list, ret_list);
- Xbad:
- X before = o_before, after = o_after, search_from = o_search_from;
- X search_subj = o_search_subj, search_to = o_search_to;
- X for (c = 0; c < 3; c++)
- X mdy[c] = o_mdy[c];
- X
- X return ret;
- X}
- X
- Xfind_pattern(p, check_list, ret_list)
- Xregister char *p;
- Xchar check_list[], ret_list[];
- X{
- X register int n, val, i; /* val is return value from regex or re_exec */
- X long bytes = 0;
- X char buf[HDRSIZ];
- X static char *err = (char *)-1;
- X#ifdef REGCMP
- X char *regcmp(), *regex();
- X#else /* REGCMP */
- X char *re_comp();
- X#endif /* REGCMP */
- X
- X if (p && *p == '\\')
- X p++; /* take care of escaping special cases (`-', `\') */
- X
- X /* specify what we're looking for */
- X if (p && *p) {
- X if (icase)
- X p = lcase_strcpy(buf, p);
- X#ifdef REGCMP
- X if (err && p)
- X xfree(err);
- X if (p && !(err = regcmp(p, NULL))) {
- X print("regcmp error: %s\n", p);
- X clear_msg_list(ret_list);
- X return -1;
- X }
- X#else /* REGCMP */
- X if (err = re_comp(p)) {
- X print("re_comp error: %s\n", err);
- X clear_msg_list(ret_list);
- X return -1;
- X }
- X#endif /* REGCMP */
- X } else if (err == (char *)-1 && mdy[1] <= 0) {
- X print("No previous regular expression\n");
- X clear_msg_list(ret_list); /* doesn't matter really */
- X return -1;
- X }
- X /* start searching: set bytes, and message number: n */
- X for (n = 0; n < msg_cnt; n++)
- X if (msg_bit(check_list, n)) {
- X if (mdy[1] > 0) {
- X int msg_mdy[3];
- X if (ison(glob_flags, DATE_RECV))
- X p = msg[n].m_date_recv;
- X else
- X p = msg[n].m_date_sent;
- X (void) sscanf(p, "%2d%2d%2d", /* yr mo da */
- X &msg_mdy[2], &msg_mdy[0], &msg_mdy[1]);
- X msg_mdy[0]--;
- X Debug("checking %d's date: %d-%d-%d ",
- X n+1, msg_mdy[0]+1, msg_mdy[1], msg_mdy[2]);
- X /* start at year and wrap around.
- X * only when match the day (4), check for == (match)
- X */
- X for (i = 2; i < 5; i++)
- X if (before && msg_mdy[i%3] < mdy[i%3]
- X || after && msg_mdy[i%3] > mdy[i%3]
- X || i == 4 && (msg_mdy[i%3] == mdy[i%3])) {
- X Debug("matched (%s).\n",
- X (i == 2)? "year" : (i == 3)? "month" : "day");
- X set_msg_bit(ret_list, n);
- X break;
- X } else if (msg_mdy[i%3] != mdy[i%3]) {
- X Debug("failed.\n");
- X break;
- X }
- X continue;
- X }
- X /* we must have the right date -- if we're searching for a
- X * string, find it.
- X */
- X (void) msg_get(n, NULL, 0);
- X bytes = 0;
- X while (bytes < msg[n].m_size) {
- X if (!search_subj && !search_from && !search_to &&
- X !*search_hdr && !(p = fgets(buf, sizeof buf, tmpf)))
- X break;
- X else if (search_subj) {
- X if (!(p = header_field(n, "subject")))
- X break;
- X } else if (search_from) {
- X if (!(p = header_field(n, "from"))) {
- X /*
- X * Check for MSG_SEPARATOR here? Maybe not...
- X */
- X register char *p2;
- X (void) msg_get(n, NULL, 0);
- X if (!(p2 = fgets(buf, sizeof buf, tmpf)) ||
- X !(p = index(p2, ' ')))
- X continue;
- X p++;
- X if (p2 = any(p, " \t"))
- X *p2 = 0;
- X }
- X } else if (search_to) {
- X if (!(p = header_field(n, "to")) &&
- X !(p = header_field(n, "apparently-to")))
- X break;
- X } else if (*search_hdr) {
- X if (!(p = header_field(n, search_hdr)))
- X break;
- X }
- X if (icase)
- X p = lcase_strcpy(buf, p);
- X#ifdef REGCMP
- X val = !!regex(err, p, NULL); /* convert value to a boolean */
- X#else /* REGCMP */
- X val = re_exec(p);
- X#endif /* REGCMP */
- X if (val == -1) { /* doesn't apply in system V */
- X print("Internal error for pattern search.\n");
- X clear_msg_list(ret_list); /* it doesn't matter, really */
- X return -1;
- X }
- X if (!val)
- X bytes += strlen(p);
- X else {
- X set_msg_bit(ret_list, n);
- X break;
- X }
- X if (search_subj || search_from || search_to || *search_hdr)
- X break;
- X }
- X }
- X return 0;
- X}
- X
- X#ifdef CURSES
- X/*
- X * search for a pattern in composed message headers -- also see next function
- X * flags == 0 forward search (prompt).
- X * flags == -1 continue search (no prompt).
- X * flags == 1 backward search (prompt).
- X */
- Xsearch(flags)
- Xregister int flags;
- X{
- X register char *p;
- X char pattern[128];
- X register int this_msg = current_msg, val = 0;
- X static char *err = (char *)-1, direction;
- X SIGRET (*oldint)(), (*oldquit)();
- X#ifdef REGCMP
- X char *regcmp();
- X#else /* REGCMP */
- X char *re_comp();
- X#endif /* REGCMP */
- X
- X if (msg_cnt <= 1) {
- X print("Not enough messages to invoke a search.\n");
- X return 0;
- X }
- X pattern[0] = '\0';
- X if (flags == -1)
- X print("continue %s search...", direction? "forward" : "backward");
- X else
- X print("%s search: ", flags? "backward" : "forward");
- X if (flags > -1)
- X if (Getstr(pattern, COLS-18, 0) < 0)
- X return 0;
- X else
- X direction = !flags;
- X#ifdef REGCMP
- X if (err && *pattern)
- X xfree(err);
- X else if (err == (char *)-1 && !*pattern) {
- X print("No previous regular expression.");
- X return 0;
- X }
- X if (*pattern && !(err = regcmp(pattern, NULL))) {
- X print("Error in regcmp in %s", pattern);
- X return 0;
- X }
- X#else /* REGCMP */
- X if (err = re_comp(pattern)) {
- X print(err);
- X return 0;
- X }
- X#endif /* REGCMP */
- X move(LINES-1, 0), refresh();
- X on_intr();
- X
- X do {
- X if (direction)
- X current_msg = (current_msg+1) % msg_cnt;
- X else
- X if (--current_msg < 0)
- X current_msg = msg_cnt-1;
- X p = compose_hdr(current_msg);
- X#ifdef REGCMP
- X val = !!regex(err, p, NULL); /* convert value to a boolean */
- X#else /* REGCMP */
- X val = re_exec(p);
- X#endif /* REGCMP */
- X if (val == -1) /* doesn't apply in system V */
- X print("Internal error for pattern search.\n");
- X } while (!val && current_msg != this_msg && isoff(glob_flags, WAS_INTR));
- X
- X if (ison(glob_flags, WAS_INTR)) {
- X print("Pattern search interrupted.");
- X current_msg = this_msg;
- X } else if (val == 0)
- X print("Pattern not found.");
- X
- X off_intr();
- X return val;
- X}
- X#endif /* CURSES */
- X
- X/*
- X * parse a user given date string and set mdy[] array with correct
- X * values. Return 0 on failure.
- X */
- Xdate1(p)
- Xregister char *p;
- X{
- X register char *p2;
- X long t;
- X int i;
- X struct tm *today;
- X
- X if (*p == '-' || *p == '+') {
- X before = !(after = *p == '+');
- X skipspaces(1);
- X }
- X if (!isdigit(*p) && *p != '/') {
- X print("syntax error on date: \"%s\"\n", p);
- X return 0;
- X }
- X (void) time (&t);
- X today = localtime(&t);
- X for (i = 0; i < 3; i++)
- X if (!p || !*p || *p == '/') {
- X switch(i) { /* default to today's date */
- X case 0: mdy[0] = today->tm_mon;
- X when 1: mdy[1] = today->tm_mday;
- X when 2: mdy[2] = today->tm_year;
- X }
- X if (p && *p)
- X p++;
- X } else {
- X p2 = (*p)? index(p+1, '/') : NULL;
- X mdy[i] = atoi(p); /* atoi will stop at the '/' */
- X if (i == 0 && (--(mdy[0]) < 0 || mdy[0] > 11)) {
- X print("Invalid month: %s\n", p);
- X return 0;
- X } else if (i == 1 && (mdy[1] < 1 || mdy[1] > 31)) {
- X print("Invalid day: %s\n", p);
- X return 0;
- X }
- X if (p = p2) /* set p to p2 and check to see if it's valid */
- X p++;
- X }
- X return 1;
- X}
- X
- X/*
- X * Parse arguments specifying days/months/years "ago" (relative to today).
- X * Legal syntax: -ago [+-][args]
- X * where "args" is defined to be:
- X * [0-9]+[ ]*[dD][a-Z]*[ ,]*[0-9]+[mM][a-Z]*[ ,]*[0-9]+[ ]*[yY][a-Z]*
- X * 1 or more digits, 0 or more spaces, d or D followed by 0 or more chars,
- X * 0 or more whitespaces or commas, repeat for months and years...
- X * Examples:
- X * 1 day, 2 months, 0 years
- X * 2 weeks 1 year
- X * 10d, 5m
- X * 3w
- X * 1d 1Y
- X *
- X * Return number of args parsed; -1 on error.
- X */
- Xago_date(argv)
- Xchar **argv;
- X{
- X#define SECS_PER_DAY (60 * 60 * 24)
- X#define SECS_PER_WEEK (SECS_PER_DAY * 7)
- X#define SECS_PER_MONTH ((int)(SECS_PER_DAY * 30.5))
- X#define SECS_PER_YEAR (SECS_PER_DAY * 365)
- X register char *p;
- X char buf[256];
- X int n = 0, value;
- X long t;
- X struct tm *today;
- X
- X (void) argv_to_string(buf, argv);
- X p = buf;
- X (void) time (&t); /* get current time in seconds and subtract new values */
- X if (*p == '-')
- X before = TRUE;
- X else if (*p == '+')
- X after = TRUE;
- X skipspaces(before || after);
- X while (*p) {
- X if (!isdigit(*p))
- X break; /* really a syntax error, but it could be other pick args */
- X p = my_atoi(p, &value); /* get 1 or more digits */
- X skipspaces(0); /* 0 or more spaces */
- X switch (lower(*p)) { /* d, m, or y */
- X case 'd' : t -= value * SECS_PER_DAY;
- X when 'w' : t -= value * SECS_PER_WEEK;
- X when 'm' : t -= value * SECS_PER_MONTH;
- X when 'y' : t -= value * SECS_PER_YEAR;
- X otherwise: return -1;
- X }
- X for (p++; Lower(*p) >= 'a' && *p <= 'z'; p++)
- X ; /* skip the rest of this token */
- X while (*p == ',' || isspace(*p))
- X ; /* 0 or more whitespaces or commas */
- X }
- X today = localtime(&t);
- X mdy[0] = today->tm_mon;
- X mdy[1] = today->tm_mday;
- X mdy[2] = today->tm_year;
- X
- X /* Count the number of args parsed */
- X for (n = 0; p > buf && *argv; n++)
- X p -= (strlen(*argv++)+1);
- X Debug("parsed %d args\n", n);
- X return n;
- X}
- END_OF_FILE
- if test 13226 -ne `wc -c <'pick.c'`; then
- echo shar: \"'pick.c'\" unpacked with wrong size!
- fi
- # end of 'pick.c'
- fi
- if test -f 'select.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'select.c'\"
- else
- echo shar: Extracting \"'select.c'\" \(13038 characters\)
- sed "s/^X//" >'select.c' <<'END_OF_FILE'
- X/* select.c (c) copyright 1986 (Dan Heller) */
- X
- X/*
- X * Routine which handle io (selection on file descriptors) between user and
- X * the various windows.
- X *
- X * In toolmode, the user types characters and each character is interpreted
- X * here and, if applicable, is sent to rite.c where it is appended to a
- X * string similar to a tty driver and fgets. When the user types a '\n' the
- X * rite() routine returns the string and we call add_to_letter to append the
- X * string to the letter. Signals are caught here as well. that is the signal
- X * characters setup by the user are checked and if one matches, call the signal
- X * handling routine as if there were a real signal.
- X *
- X * Mouse handling is done here. See code for more detail.
- X */
- X#include "mush.h"
- X
- X#define READ_MSG (char *)'r'
- X#define DEL_MSG (char *)'d'
- X#define UNDEL_MSG (char *)'u'
- X#define REPL_MSG (char *)'R'
- X#define SAVE_MSG (char *)'s'
- X#define PRNT_MSG (char *)'p'
- X#define PRE_MSG (char *)'P'
- X#define E_EDIT (char *)'e'
- X#define E_VIEW (char *)'v'
- X#define E_INCLUDE (char *)'i'
- X#define E_SEND (char *)'S'
- X#define E_ABORT (char *)'a'
- X#define MENU_HELP (char *)'h'
- X#define O_SAVE (char *)'s'
- X#define O_QUIT (char *)'q'
- X#define O_RSTR (char *)'r'
- X
- X#define N_MENU_ITEMS 8
- X#define E_MENU_ITEMS 6
- X
- Xmsg_io(gfxsw, ibits, obits, ebits, timer)
- Xregister struct gfxsubwindow *gfxsw;
- Xregister int *ibits,*obits,*ebits;
- Xstruct timeval **timer;
- X{
- X register char *p;
- X struct inputevent event;
- X static char lastchar;
- X static int line, count;
- X
- X if (*ibits & ~(1 << gfxsw->gfx_windowfd)) {
- X *ibits = *obits = *ebits = 0;
- X return;
- X }
- X if (input_readevent(msg_sw->ts_windowfd, &event) == -1) {
- X error("input event");
- X return;
- X }
- X /*
- X if (ID == LOC_WINENTER) {
- X int x;
- X struct inputmask im;
- X win_getinputmask(gfxsw->gfx_windowfd, &im, &x);
- X win_setinputmask(hdr_sw->ts_windowfd, &im, &im, x);
- X }
- X */
- X if (ID >= KEY_LEFTFIRST)
- X if (ison(glob_flags, IS_GETTING))
- X print("Finish editing letter first");
- X else
- X (void) func_key(ID);
- X else if (isascii(ID) && (msg_pix || ison(glob_flags, IS_GETTING) ||
- X getting_opts)) {
- X if (getting_opts) {
- X /*
- X * txt.x <= 5 indicates not to accept typed input for options
- X * and function key setting.
- X */
- X if (txt.x > 5) {
- X /* ^C, ^\ or ^U kills line */
- X type_cursor(PIX_XOR);
- X if (ID == tchars.t_intrc || ID == tchars.t_quitc ||
- X ID == _tty.sg_kill) {
- X rite(_tty.sg_kill), txt.x = 5;
- X if (getting_opts == 1)
- X option_line(line), display_opts(0);
- X else
- X set_key(0, 0, 0);
- X } else if (p = rite((char)ID)) {
- X /* if no string entered, preserve old value */
- X if (*p && getting_opts == 1)
- X add_opt(p, line);
- X if (getting_opts == 2)
- X set_key(p, 0,0);
- X } else
- X type_cursor(PIX_XOR);
- X }
- X }
- X /*
- X * This section MUST BE BEFORE the following "is_getting" section.
- X * If user displays a message while editing a letter, he must hit 'q'
- X * to return to edit mode. He may not edit a new letter while one is
- X * already being edited.
- X */
- X else if (msg_pix)
- X if (isdigit(ID)) {
- X if (!isdigit(lastchar))
- X count = 0;
- X count = count * 10 + ID - '0';
- X } else {
- X /* scroll <count> lines */
- X if (!count)
- X count = 1;
- X if (ID == 'k' || ID == 'K' || ID == '-')
- X scroll_win(-count);
- X else if (ID == '\n' || ID == '\r' || ID == 'j' ||
- X ID == 'J' || ID == '+')
- X scroll_win(count);
- X else if (ID == ' ')
- X scroll_win(crt-3);
- X else if ((ID == 'q' || ID == 'Q') &&
- X ison(glob_flags, IS_GETTING)) {
- X pr_destroy(msg_pix), msg_pix = (struct pixrect *)NULL;
- X win_setcursor(msg_sw->ts_windowfd, &write_cursor);
- X txt.x = 5, txt.y = msg_rect.r_height - l_height(curfont);
- X wprint("\n(continue editing letter)\n");
- X clr_bot_line();
- X type_cursor(PIX_SRC);
- X }
- X }
- X /*
- X * If msg_pix is NULL, then we are not reading a message. If we are
- X * editing a letter, then enter the keys typed. If we are doing
- X * nothing, ignore this input.
- X */
- X else if (ison(glob_flags, IS_GETTING)) {
- X type_cursor(PIX_XOR);
- X if (lastchar != ltchars.t_lnextc &&
- X (ID == tchars.t_intrc || ID == tchars.t_quitc)) {
- X (void) rite(_tty.sg_kill);
- X (void) rm_edfile(SIGINT);
- X } else {
- X register int n = 1;
- X if (ID == tchars.t_eofc && txt.x == 5
- X || (p = rite((char)ID)) && !(n = add_to_letter(p)))
- X finish_up_letter();
- X else if (n > 0)
- X type_cursor(PIX_XOR);
- X }
- X }
- X lastchar = ID;
- X } else switch(ID) {
- X when MS_LEFT : case MS_MIDDLE:
- X if (getting_opts == 2)
- X if (ID == MS_LEFT)
- X set_key(NULL, event.ie_locx, event.ie_locy);
- X else {
- X register char *p = find_key(event.ie_locx, event.ie_locy);
- X if (p)
- X print("Function key %s: %s", p, key_set_to(p));
- X }
- X else if (getting_opts) {
- X int y = event.ie_locy - 50;
- X if (y < -24)
- X break;
- X if (y < 0) {
- X register int x = event.ie_locx;
- X register int X = 60*l_width(LARGE);
- X if (x >= X && x <= X+16)
- X display_opts(-1); /* scroll options back one value */
- X else if (x >= X+20 && x <= X+36)
- X display_opts(1); /* scroll options forward one value */
- X break;
- X }
- X /* the user was typing something -- stopped by using mouse */
- X if (txt.x > 5) {
- X type_cursor(PIX_CLR);
- X (void) rite(_tty.sg_kill), txt.x = 5;
- X option_line(line), display_opts(0);
- X }
- X line = y/20;
- X if (ID == MS_LEFT)
- X toggle_opt(line);
- X help_opt(line); /* display help (short info) in both cases */
- X } else if (msg_pix)
- X if (ID == MS_LEFT)
- X scroll_win(crt-3);
- X else
- X scroll_win(-(crt-3));
- X when MS_RIGHT:
- X if (getting_opts)
- X (void) view_opts_menu(&event, gfxsw->gfx_windowfd);
- X else if (isoff(glob_flags, IS_GETTING))
- X (void) do_menu(&event, gfxsw->gfx_windowfd, current_msg);
- X else
- X (void) edit_menu(&event, gfxsw->gfx_windowfd);
- X otherwise: ;
- X }
- X *ibits = *obits = *ebits = 0;
- X}
- X
- Xstruct cursor *mice[3] = { &l_cursor, &m_cursor, &r_cursor };
- X
- Xhdr_io(gfxsw, ibits, obits, ebits, sw_timer)
- Xregister struct gfxsubwindow *gfxsw;
- Xint *ibits,*obits,*ebits;
- Xstruct timeval **sw_timer;
- X{
- X static int which_cursor;
- X struct inputmask im;
- X struct inputevent event;
- X int line;
- X
- X if (*ibits & ~(1 << gfxsw->gfx_windowfd)) {
- X *ibits = *obits = *ebits = 0;
- X return;
- X }
- X /* make curosr change which button is lit */
- X win_setcursor(gfxsw->gfx_windowfd, mice[which_cursor]);
- X
- X which_cursor = (which_cursor+1) % 3;
- X if (input_readevent(hdr_sw->ts_windowfd, &event) == -1) {
- X error("input event");
- X return;
- X }
- X /* I'm not sure why I have to do this.
- X * I'm doing it because sometimes the IO hangs completely and no input
- X * is accepted. What I do here is get the current mask, save it, then
- X * reset it. This action seems to flush the IO queue, and I don't have hung
- X * IO anymore. This shouldn't be necessary, but it appears to work.
- X * (occurances have droped about 90%)
- X */
- X if (ID == LOC_WINENTER) {
- X int x;
- X win_getinputmask(gfxsw->gfx_windowfd, &im, &x);
- X win_setinputmask(hdr_sw->ts_windowfd, &im, &im, x);
- X }
- X /* just return -- we just wanted to make the cursor flicker */
- X if (ID == LOC_STILL || ID == LOC_MOVE || ID == LOC_WINENTER) {
- X *ibits = *obits = *ebits = 0;
- X return;
- X }
- X line = event.ie_locy / l_height(DEFAULT);
- X if (ID >= KEY_LEFTFIRST)
- X (void) func_key(ID);
- X else if (n_array[line] > msg_cnt)
- X if (!msg_cnt)
- X print("-- You have no messages -- ");
- X else
- X print("Message out of range. Place mouse over a legal message.");
- X else switch(ID) {
- X when MS_LEFT: case MS_MIDDLE:
- X (void) do_menu((ID == MS_LEFT)? READ_MSG: DEL_MSG, 0,n_array[line]);
- X when MS_RIGHT:
- X (void) do_menu(&event, gfxsw->gfx_windowfd, n_array[line]);
- X otherwise : print("Unkown ID = %d", ID);
- X }
- X *ibits = *obits = *ebits = 0;
- X}
- X
- X/* if "fd" is 0, then event points to the action to be taken.
- X * otherwise, determine action to be taken by displaying a menu.
- X * message is the number current_msg should be changed to (may be the same).
- X */
- Xdo_menu(event, fd, message)
- Xcaddr_t event;
- X{
- X static char buf[20];
- X struct menuitem *m_item;
- X char *action;
- X static struct menuitem msg_menu_items[] = {
- X { MENU_IMAGESTRING, "Read", READ_MSG },
- X { MENU_IMAGESTRING, "Delete", DEL_MSG },
- X { MENU_IMAGESTRING, "Undelete", UNDEL_MSG },
- X { MENU_IMAGESTRING, "Reply", REPL_MSG },
- X { MENU_IMAGESTRING, "Save", SAVE_MSG },
- X { MENU_IMAGESTRING, "Preserve", PRE_MSG },
- X { MENU_IMAGESTRING, "Print", PRNT_MSG },
- X { MENU_IMAGESTRING, "Help", MENU_HELP }
- X };
- X static struct menu help_menu = {
- X MENU_IMAGESTRING, "Item Help",
- X N_MENU_ITEMS, msg_menu_items,
- X (struct menu *)NULL, NULL
- X };
- X static struct menu msgs_menu = {
- X MENU_IMAGESTRING, buf, N_MENU_ITEMS,
- X msg_menu_items, &help_menu, NULL
- X };
- X /* to have the menu stack maintain order of menus upon each invokation,
- X * declare menu_ptr to be static and remove the following two lines
- X * after the declaration.
- X */
- X struct menu *menu_ptr = &msgs_menu;
- X msgs_menu.m_next = &help_menu;
- X help_menu.m_next = (struct menu *)NULL;
- X
- X if (!msg_cnt) {
- X print("No Messages.");
- X return;
- X }
- X if (fd) {
- X (void) sprintf(buf, "Message #%d", message+1);
- X if (m_item = menu_display(&menu_ptr, (struct inputevent *)event, fd))
- X action = m_item->mi_data;
- X else
- X return;
- X } else
- X action = event;
- X
- X if (menu_ptr == &help_menu || action == MENU_HELP) {
- X switch(action) {
- X when DEL_MSG: case UNDEL_MSG:
- X (void) help(fd, "menu_delete", tool_help);
- X when READ_MSG: (void) help(fd, "next", tool_help);
- X when REPL_MSG: (void) help(fd, "menu_respond", tool_help);
- X when SAVE_MSG: (void) help(fd, "save", tool_help);
- X when PRE_MSG: (void) help(fd, "preserve", tool_help);
- X when PRNT_MSG: (void) help(fd, "printer", tool_help);
- X when MENU_HELP:
- X if (menu_ptr == &help_menu)
- X (void) help(fd, "help_menu_help_msg", tool_help);
- X else
- X (void) help(fd, "msg_menu", tool_help);
- X }
- X return;
- X }
- X set_isread(message);
- X if (action == SAVE_MSG) {
- X panel_set(msg_num_item, PANEL_VALUE, sprintf(buf, "%d", message+1), 0);
- X ((struct inputevent *)event)->ie_code = MS_LEFT;
- X do_file_dir(save_item, 0, event);
- X panel_set(msg_num_item, PANEL_VALUE, NO_STRING, 0);
- X return;
- X } else if (action == PRNT_MSG || action == PRE_MSG ||
- X action == UNDEL_MSG || action == DEL_MSG) {
- X fkey_misc(action, message);
- X return;
- X }
- X if (isoff(glob_flags, IS_GETTING)) {
- X current_msg = message;
- X (void) do_hdrs(0, DUBL_NULL, NULL);
- X }
- X if (action == REPL_MSG) {
- X respond_mail(respond_item, 0, event);
- X return;
- X } else if (ison(glob_flags, IS_GETTING)) {
- X if (exec_pid)
- X /* User can read a message as long as he's not in an editor */
- X print("Finish editing message first");
- X else {
- X (void) do_hdrs(0, DUBL_NULL, NULL);
- X display_msg(message, (long)0);
- X }
- X return;
- X }
- X display_msg(current_msg, (long)0);
- X}
- X
- X/* miscellaneous function key actions there are here because the defines
- X * for DEL_MSG, etc are here in this file and the function is called from
- X * here more often.
- X */
- Xfkey_misc(action, message)
- Xchar *action;
- X{
- X int argc;
- X register char **argv;
- X char buf[30];
- X
- X print("Message #%d ", message+1);
- X if (action == UNDEL_MSG || action == DEL_MSG)
- X print_more("%sd. ", sprintf(buf, "%selete",
- X (action == DEL_MSG)? "d": "und"));
- X else if (action == PRNT_MSG) {
- X print_more("sent to printer");
- X (void) strcpy(buf, "lpr");
- X } else if (action == PRE_MSG)
- X print_more("%sd", strcpy(buf, "preserve"));
- X (void) sprintf(&buf[strlen(buf)], " %d", message+1);
- X if (message == current_msg && action == DEL_MSG)
- X do_clear();
- X
- X if (argv = make_command(buf, DUBL_NULL, &argc))
- X (void) do_command(argc, argv, msg_list);
- X return;
- X}
- X
- Xview_opts_menu(event, fd)
- Xstruct inputevent *event;
- X{
- X static char buf[5];
- X struct menuitem *m_item;
- X char *action;
- X static struct menuitem opts_items[] = {
- X { MENU_IMAGESTRING, "Save Options", O_SAVE },
- X { MENU_IMAGESTRING, "Restore Options", O_RSTR },
- X { MENU_IMAGESTRING, "Quit Options", O_QUIT },
- X { MENU_IMAGESTRING, "Help", MENU_HELP }
- X };
- X static struct menu msgs_menu = {
- X MENU_IMAGESTRING, "Options", 4, opts_items, (struct menu *)NULL, NULL
- X };
- X struct menu *menu_ptr = &msgs_menu;
- X
- X if (m_item = menu_display(&menu_ptr, event, fd))
- X action = m_item->mi_data;
- X else
- X return;
- X switch(action) {
- X case O_SAVE:
- X save_opts(0, DUBL_NULL);
- X when O_RSTR:
- X init();
- X if (getting_opts == 1)
- X view_options();
- X else
- X set_fkeys();
- X when O_QUIT:
- X do_clear();
- X unlock_cursors(); /* actually resets msg_win's cursor */
- X if (isoff(glob_flags, IS_GETTING) && msg_cnt)
- X if (isoff(msg[current_msg].m_flags, DELETE))
- X display_msg(current_msg, (long)0);
- X else
- X (void) read_mail(NO_ITEM, 0, NO_EVENT);
- X when MENU_HELP:
- X (void) help(fd, (getting_opts == 1)? "options": "fkeys", tool_help);
- X }
- X}
- END_OF_FILE
- if test 13038 -ne `wc -c <'select.c'`; then
- echo shar: \"'select.c'\" unpacked with wrong size!
- fi
- # end of 'select.c'
- fi
- if test -f 'viewopts.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'viewopts.c'\"
- else
- echo shar: Extracting \"'viewopts.c'\" \(13307 characters\)
- sed "s/^X//" >'viewopts.c' <<'END_OF_FILE'
- X/* @(#)viewopts.c (c) copyright 10/18/86 (Dan Heller) */
- X
- X#include "mush.h"
- X
- Xstruct viewopts {
- X char *v_opt;
- X char *v_prompt;
- X int v_usage;
- X#define TOOL 01
- X#define TEXT 02
- X char *v_description;
- X};
- X
- X/*
- X * struct contains the option, a prompt if it has a string value, whether
- X * or not it applies to non suntools, line mode, or both, and a
- X * string describing what the option does. If the prompt string starts
- X * with a minus sign, then the value can be set without a value. This
- X * is there to indicate to option_line to print a toggle (cycle) pixrect
- X * and to print TRUE/FALSE telling whether the value is on or off regardless
- X * of it's "string" value.
- X */
- Xstruct viewopts viewopts[] = {
- X { "alwaysignore", NULL, TOOL | TEXT,
- X "Always ignore the message headers on the 'ignored' list." },
- X { "ask", NULL, TOOL | TEXT,
- X "Prompts for a subject on outgoing mail." },
- X { "askcc", NULL, TOOL | TEXT,
- X "Ask for list of Carbon Copy recipients whenever sending mail." },
- X { "autodelete", NULL, TOOL | TEXT,
- X "Automatically delete ALL READ messages whenever you update mail." },
- X { "autoedit", NULL, TOOL | TEXT,
- X "Automatically enter editor whenever you REPLY to mail." },
- X { "autoinclude", NULL, TOOL | TEXT,
- X "Include a copy of author's message each time you reply to mail." },
- X { "autoprint", NULL, TOOL | TEXT,
- X "Display the next message on the list when you delete a message." },
- X { "auto_route", NULL, TOOL | TEXT,
- X "Remove redundant uucp addresses when replying to messages." },
- X { "autosign", "-Filename", TOOL | TEXT,
- X "Add file (~/.signature if set but no value) at end of all letters." },
- X { "autosign2", "Address : Filename", TOOL | TEXT,
- X "Signature to use for specific addresses. \"addr, ... : <signature>\""},
- X { "cdpath", "Path", TEXT,
- X "Path to search for directories when the \"cd\" command is issued." },
- X { "crt", "Lines", TEXT,
- X "The number of lines a message must have for 'pager' to be invoked." },
- X { "date_received", NULL, TOOL | TEXT,
- X "Time displayed for message headers shows date received (or sent)." },
- X { "dead", "Filename", TOOL | TEXT,
- X "The name of the file to store dead mail (default = ~/dead.letter)." },
- X { "dot", NULL, TOOL | TEXT,
- X "Allow \".\" on a line by itself to send letter." },
- X { "editor", "Editor name/path", TOOL | TEXT,
- X "Editor for message editing (default = env EDITOR or \"vi\")." },
- X { "escape", "Character", TOOL | TEXT,
- X "Escape character for extended editing commands (default = ~)." },
- X { "folder", "Pathname", TOOL | TEXT,
- X "Full pathname to the directory where personal folders are kept." },
- X { "fortune", "-Flag", TOOL | TEXT,
- X "Add fortune to end of letters. Flag to \"fortune\" is optional." },
- X { "fortunates", "Users", TOOL | TEXT,
- X "Those who will receive fortunes if fortune is set (default: All)." },
- X { "hdr_format", "Format", TOOL | TEXT,
- X "Formatting string for headers. \"headers -?\" or help hdr_format." },
- X { "history", "Number", TEXT,
- X "How many commands to remember (like csh)." },
- X { "hold", NULL, TOOL | TEXT,
- X "Read but not deleted messages are saved in spool -- not mbox." },
- X { "home", "Directory", TOOL | TEXT,
- X "The user's home directory." },
- X { "hostname", "Hostname", TOOL | TEXT,
- X "User-definable name for the name of your machine." },
- X { "ignore_bang", NULL, TEXT,
- X "Ignore '!' as a history reference. Otherwise, escape by: \\!" },
- X { "ignoreeof", "-Command", TEXT,
- X "Ignores ^D as exit, or (if set), execute \"command\"." },
- X { "indent_str", "String", TOOL | TEXT,
- X "String to offset included messages within your letters." },
- X { "in_reply_to", NULL, TOOL | TEXT,
- X "When responding to mail, add In-Reply-To: to message headers." },
- X { "keepsave", NULL, TOOL | TEXT,
- X "Prevents messages from being marked as `deleted' when you `save'." },
- X { "known_hosts", "Host list", TOOL | TEXT,
- X "List of hosts that your site is known to uucp mail to." },
- X { "lister", "Arguments", TOOL | TEXT,
- X "Arguments passed to the 'ls' command." },
- X { "logfile", "Filename", TOOL | TEXT,
- X "Log outgoing mail headers only. Message text not logged." },
- X { "mbox", "Filename", TOOL | TEXT,
- X "Filename to use instead of ~/mbox for default mailbox." },
- X { "metoo", NULL, TOOL | TEXT,
- X "When replying to mail, metoo preserves your name on mailing list." },
- X { "mil_time", NULL, TOOL | TEXT,
- X "24-hour military time format is used whenever a time is printed. " },
- X { "newline", "-Command", TEXT,
- X "Ignore RETURN. If set to a command, execute that command." },
- X { "no_expand", NULL, TEXT | TOOL,
- X "Prevents expansion of Mush aliases in outgoing mail headers." },
- X { "no_hdrs", NULL, TOOL | TEXT,
- X "If set, personalized headers are NOT inserted to outgoing mail." },
- X { "no_reverse", NULL, TOOL | TEXT,
- X "Disables reverse video in curses mode -- uses \"bold\" in tool mode."},
- X { "nonobang", NULL, TEXT,
- X "Suppresses errors from unsuccessful history references." },
- X { "nosave", NULL, TOOL | TEXT,
- X "Prevents aborted mail from being saved in $dead." },
- X { "pager", "Program", TEXT,
- X "Program name to be used as a pager for messages longer than crt." },
- X { "pre_indent_str", "String", TEXT | TOOL,
- X "String to precede message text interpolated into message body." },
- X { "post_indent_str", "String", TEXT | TOOL,
- X "String to succeed message text interpolated into message body." },
- X { "print_cmd", "Program", TOOL | TEXT,
- X "Alternate program to use to send messages to the printer." },
- X { "printer", "Printer", TOOL | TEXT,
- X "Printer to send messages to (default = environment PRINTER)." },
- X { "prompt", "String", TEXT,
- X "Your prompt. \"help prompt\" for more information." },
- X { "quiet", NULL, TEXT,
- X "Don't print the version number of Mush on startup." },
- X { "realname", "Name:", TOOL | TEXT,
- X "Your real name." },
- X { "record", "Filename", TOOL | TEXT,
- X "Save all outgoing mail in specified filename." },
- X { "reply_to_hdr", "Headers", TOOL | TEXT,
- X "List of headers use to construct reply addresses from a message." },
- X { "save_empty", NULL, TOOL | TEXT,
- X "Folders which have all messages deleted are NOT removed on updates." },
- X { "screen", "Number of Headers", TEXT,
- X "Number of headers to print in non-suntools (text) mode." },
- X { "screen_win", "Number of Headers", TOOL,
- X "Set the size of the header window for the tool mode only." },
- X { "show_deleted", NULL, TOOL | TEXT,
- X "Show deleted messages in headers listings (unused in curses mode)." },
- X { "show_hdrs", "Headers", TOOL | TEXT,
- X "When displaying a message, show list of \"headers\" only." },
- X { "sendmail", "Program", TOOL | TEXT,
- X "Program to use to deliver mail instead of using the default."},
- X { "sort", "-Option", TOOL | TEXT,
- X "Pre-sorting of messages on mush startup (set to valid sort option)." },
- X { "squeeze", NULL, TOOL | TEXT,
- X "When reading messages, squeeze all blank lines into one." },
- X { "thisfolder", NULL, TEXT,
- X "This read-only variable gives the current folder name." },
- X { "toplines", "Lines", TOOL | TEXT,
- X "Number of lines to print of a message for the 'top' command." },
- X { "tmpdir", "Directory", TOOL | TEXT,
- X "Directory to use for temporary files used by Mush." },
- X { "unix", NULL, TEXT,
- X "Non-mush commands are considered to be UNIX commands." },
- X { "verify", NULL, TEXT,
- X "Verify to send, re-edit, or abort letter after editing." },
- X { "visual", "Visual editor", TOOL | TEXT,
- X "Visual editor for messages (default = $editor or env VISUAL)."},
- X { "warning", NULL, TOOL | TEXT,
- X "Print warning messages for non-fatal errors." },
- X { "wrap", NULL, TOOL | TEXT,
- X "After referencing last message, message pointer wraps to start." },
- X { "wrapcolumn", "-Column to wrap [78]", TEXT,
- X "Column at which to wrap lines when composing messages." },
- X};
- X
- X#define total_opts (sizeof viewopts / sizeof (struct viewopts))
- X
- X#ifdef SUNTOOL
- X
- Xstatic int start_cnt;
- X
- X#define twenty 5 + 20*l_width(DEFAULT)
- X#define forty 5 + 40*l_width(DEFAULT)
- X#define image_at(x,y,image) pw_rop(msg_win, x, y, 16, 16, PIX_SRC, image, 0,0)
- X
- X/* print in default text, but increment in large text segments */
- Xview_options()
- X{
- X if (msg_rect.r_height < 80) {
- X print("Window not big enough to display options.");
- X return;
- X }
- X do_clear();
- X getting_opts = 1, start_cnt = 0;
- X win_setcursor(msg_sw->ts_windowfd, &checkmark);
- X highlight(msg_win, txt.x, txt.y, LARGE,
- X " : Toggle Value : Description : Menu (Help)");
- X image_at(txt.x + 2 * l_width(DEFAULT), txt.y - 12, &mouse_left);
- X image_at(txt.x + 25 * l_width(DEFAULT), txt.y - 12, &mouse_middle);
- X image_at(txt.x + 48 * l_width(DEFAULT), txt.y - 12, &mouse_right);
- X
- X pw_vector(msg_win, 0, txt.y+6, msg_rect.r_width, txt.y+6, PIX_SRC, 1);
- X pw_vector(msg_win, 0, txt.y+8, msg_rect.r_width, txt.y+8, PIX_SRC, 1);
- X
- X txt.y += 24;
- X
- X pw_text(msg_win, 5, txt.y, PIX_SRC, fonts[LARGE], "Option");
- X pw_text(msg_win, twenty, txt.y, PIX_SRC, fonts[LARGE], "On/Off");
- X pw_text(msg_win, forty, txt.y, PIX_SRC, fonts[LARGE], "Values");
- X
- X pw_vector(msg_win, 0, txt.y+6, msg_rect.r_width, txt.y+6, PIX_SRC, 1);
- X pw_vector(msg_win, 0, txt.y+8, msg_rect.r_width, txt.y+8, PIX_SRC, 1);
- X
- X pw_text(msg_win, 59*l_width(DEFAULT),txt.y,PIX_SRC,fonts[LARGE],"Scroll:");
- X pw_rop(msg_win, 60*l_width(LARGE), txt.y-13,16,16,PIX_SRC, &dn_arrow,0,0);
- X pw_rop(msg_win, 60*l_width(LARGE)+20,txt.y-13,16,16,PIX_SRC, &up_arrow,0,0);
- X
- X display_opts(0); /* create the pixrect and all that */
- X}
- X
- Xdisplay_opts(count)
- Xregister int count;
- X{
- X register int total_displayable = (msg_rect.r_height - 60) / 20;
- X
- X if (count < 0 && start_cnt + count < 0) {
- X print("At the beginning");
- X return;
- X } else if (count && start_cnt + count + total_displayable > total_opts) {
- X print("At the end");
- X return;
- X }
- X start_cnt += count;
- X if (!msg_pix) {
- X register int x = (total_opts+1) * 20;
- X if (x < msg_rect.r_height)
- X x = msg_rect.r_height;
- X if (!(msg_pix = mem_create(msg_rect.r_width, x, 1))) {
- X error("mem_create");
- X return;
- X }
- X pr_rop(msg_pix,0,0, msg_rect.r_width-1, x-1, PIX_CLR,0,0,0);
- X for (count = 0; count < total_opts; count++)
- X option_line(count);
- X }
- X pw_rop(msg_win, 0, 50, msg_rect.r_width - 1, msg_rect.r_height - 50,
- X PIX_SRC, msg_pix, 0, start_cnt * 20);
- X}
- X
- Xvoid
- Xtoggle_opt(line)
- X{
- X register char *p = viewopts[start_cnt+line].v_prompt;
- X
- X if (do_set(set_options, viewopts[start_cnt+line].v_opt))
- X un_set(&set_options, viewopts[start_cnt+line].v_opt);
- X else {
- X if (p) {
- X txt.x = 5 + 40 * l_width(DEFAULT) +
- X (1 + strlen(p) - (*p=='-')) * l_width(DEFAULT);
- X txt.y = 50 + line*20 + l_height(curfont);
- X }
- X if (!p || *p == '-') {
- X register char *argv[2];
- X argv[0] = viewopts[start_cnt+line].v_opt;
- X argv[1] = NULL;
- X (void) add_option(&set_options, argv);
- X }
- X }
- X option_line(line);
- X display_opts(0);
- X if (txt.x > 5)
- X type_cursor(PIX_SRC);
- X}
- X
- Xvoid
- Xhelp_opt(line)
- X{
- X print(viewopts[start_cnt+line].v_description);
- X}
- X
- Xadd_opt(p, line)
- Xregister char *p;
- X{
- X char buf[80], **argv;
- X int argc;
- X u_long save_bang = ison(glob_flags, IGN_BANG);
- X
- X (void) sprintf(buf, "set %s=\"%s\"", viewopts[start_cnt+line].v_opt, p);
- X turnon(glob_flags, IGN_BANG);
- X if (argv = make_command(buf, DUBL_NULL, &argc))
- X (void) do_command(argc, argv, msg_list);
- X if (!save_bang)
- X turnoff(glob_flags, IGN_BANG);
- X option_line(line); /* make sure new value is entered into database */
- X}
- X
- Xoption_line(count)
- Xregister int count;
- X{
- X register char *p, *v = do_set(set_options, viewopts[start_cnt+count].v_opt);
- X struct pr_prpos win;
- X
- X win.pr = msg_pix;
- X win.pos.y = (start_cnt + count) * 20 + 16;
- X win.pos.x = 5;
- X
- X pf_text(win, PIX_SRC, fonts[DEFAULT], blank);
- X pf_text(win, PIX_SRC, fonts[DEFAULT], viewopts[start_cnt+count].v_opt);
- X win.pos.x = twenty+20;
- X
- X if (!(p = viewopts[start_cnt+count].v_prompt) || *p == '-') {
- X pr_rop(msg_pix, twenty, win.pos.y-10, 16, 16, PIX_SRC, &cycle, 0, 0);
- X pf_text(win, PIX_SRC, fonts[DEFAULT], (v)? "TRUE ": "FALSE");
- X win.pos.x++;
- X pf_text(win, PIX_SRC, fonts[DEFAULT], (v)? "TRUE ": "FALSE");
- X }
- X if (p) {
- X if (*p == '-')
- X p++;
- X win.pos.x = forty;
- X /* highlight */
- X pf_text(win, PIX_SRC, fonts[DEFAULT], p);
- X win.pos.x++;
- X pf_text(win, PIX_SRC, fonts[DEFAULT], p);
- X win.pos.x = forty + strlen(p) * l_width(DEFAULT);
- X pf_text(win, PIX_SRC, fonts[DEFAULT], ":");
- X if (v) {
- X win.pos.x += (2 * l_width(DEFAULT));
- X pf_text(win, PIX_SRC, fonts[DEFAULT], v);
- X }
- X }
- X}
- X
- X#endif /* SUNTOOL */
- X
- X/*
- X * return a string describing a variable.
- X * parameters: count, str, buf.
- X * If str != NULL, check str against ALL variables
- X * in viewopts array. The one that matches, set count to it and
- X * print up all the stuff from the viewopts[count] into the buffer
- X * space in "buf" and return it.
- X */
- Xchar *
- Xvariable_stuff(count, str, buf)
- Xregister char *str, buf[];
- X{
- X if (str)
- X for (count = 0; count < total_opts; count++)
- X if (!strcmp(str, viewopts[count].v_opt))
- X break;
- X if (count >= total_opts) {
- X (void) sprintf(buf, "%s: Not a default %s variable.",
- X str? str : itoa(count), prog_name);
- X return NULL;
- X }
- X return sprintf(buf, "%s: %s",
- X viewopts[count].v_opt, viewopts[count].v_description);
- X}
- END_OF_FILE
- if test 13307 -ne `wc -c <'viewopts.c'`; then
- echo shar: \"'viewopts.c'\" unpacked with wrong size!
- fi
- # end of 'viewopts.c'
- fi
- echo shar: End of archive 6 \(of 19\).
- cp /dev/null ark6isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 19 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-